/*
 * File:   F04.h
 * Author: jcrada
 *
 * Created on 30 May 2011, 12:11 PM
 */

#ifndef ECB_CEC10_F04_H
#define	ECB_CEC10_F04_H

#include "ecb/benchmarks/cec10/CecProblem.h" 

#include "ecb/benchmarks/cec10/CecMath.h"
#include "ecb/operator/Permuted.h"
#include "ecb/operator/Grouped.h"
#include "ecb/operator/Shifted.h"
#include "ecb/benchmarks/cec10/CecRotated.h"
#include "ecb/function/Elliptic.h"


namespace ecb{
    namespace cec10 {

        class F04 : public CecProblem {
        private:
            Function* rotatedElliptic, *elliptic;
        public:

            F04(int dimensions, int mValue)
            : CecProblem("F04", "Single-group Shifted and m-rotated Elliptic Function",
            dimensions, -100, 100, true, mValue, new CecRandom(4l)) {
                std::vector<scalar> shift = CecMath::ShiftVector(dimensions, _properties->getMinimum(), _properties->getMaximum(), randomizer());
                std::vector<int> permutation = CecMath::PermutationVector(dimensions, randomizer());
                std::vector<std::vector<scalar> > rotation = CecMath::RotationMatrix(mValue, randomizer());

                std::vector<scalar> permutedShift(dimensions, 0);
                for (int i = 0; i < dimensions; ++i) {
                    permutedShift[i] = shift[permutation[i]];
                }

                rotatedElliptic = new Permuted(permutation, new Grouped(0, mValue,
                        new Shifted(permutedShift, 0,
                        new CecRotated(rotation, new Elliptic()))));

                elliptic = new Permuted(permutation, new Grouped(mValue, dimensions,
                        new Shifted(permutedShift, mValue,
                        new Elliptic())));
            }

            ~F04() {
                delete elliptic;
                delete rotatedElliptic;
            }

            scalar f(const std::vector<scalar>& x) {
                return rotatedElliptic->f(x) * 1e6 + elliptic->f(x);
            }
        };
    }
}

#endif	/* ECB_CEC10_F04_H */

